package model

import (
	"common/config"
	"common/helper"
	"context"
	"errors"
	"fmt"
	"member/contrib/conn"
	"member/contrib/session"
	ryrpc "member/rpc"
	"time"

	"github.com/ip2location/ip2location-go/v9"

	"github.com/bytedance/gopkg/util/xxhash3"
	g "github.com/doug-martin/goqu/v9"
	_ "github.com/doug-martin/goqu/v9/dialect/mysql"
	"github.com/go-redis/redis/v8"
	"github.com/jmoiron/sqlx"
	"github.com/meilisearch/meilisearch-go"
	"lukechampine.com/frand"
)

type MetaTable struct {
	MerchantDB    *sqlx.DB
	SlaveDB       *sqlx.DB
	MerchantBean  *conn.Connection
	MerchantRedis *redis.Client
	IpDB          *ip2location.DB
	Program       string //用来标识哪个台子 取 prefix 配置(5)
	SecretKey     string
	Callback      string
	WebUrl        string
	Contate       string
	Email         Email
	AwsEmail      AwsEmail
	Rand          *frand.RNG
	Meili         *meilisearch.Client
	TgPay         TgPay
	RedisDBIndex  int
}

var (
	loc                       *time.Location
	meta                      *MetaTable
	ctx                       = context.Background()
	dialect                   = g.Dialect("mysql")
	colsPayFactory            = helper.EnumFields(TblPayFactory{})
	colsMemberVip             = helper.EnumFields(MemberVip{})
	colsPromoSignConfig       = helper.EnumFields(PromoSignConfig{})
	colsPromoSignRecord       = helper.EnumFields(PromoSignRecord{})
	colsPromoSignRewardRecord = helper.EnumFields(PromoSignRewardRecord{})
	colsPromoTreasureConfig   = helper.EnumFields(PromoTreasureConfig{})
	colsPromoTreasureRecord   = helper.EnumFields(PromoTreasureRecord{})
	colsDeposit               = helper.EnumFields(TblDeposit{})
	colsWithdraw              = helper.EnumFields(tblWithdraw{})
	colsBankcard              = helper.EnumFields(TblMemberBankcard{})
	colsPromoDeposit          = helper.EnumFields(config.PromoDepositConfig{})
	colsGame                  = helper.EnumFields(Game{})
	colsInviteRecord          = helper.EnumFields(tblPromoInviteRecord{})
	colsReportAgency          = helper.EnumFields(TblReportAgency{})
	colsBankType              = helper.EnumFields(TblBanktype{})
	colsReportUser            = helper.EnumFields(tblReportUser{})
	colsPromoWeeklyConfig     = helper.EnumFields(tblPromoWeekBetConfig{})
	colsBonusConfig           = helper.EnumFields(TblBonusConfig{})
	colsTurntableReview       = helper.EnumFields(ryrpc.TblPddTurntableReview{})
	colsPlatform              = helper.EnumFields(PlatJson{})
	colsDepositPixel          = helper.EnumFields(TblDepositPixel{})
)

func GetMasterDBInstance() *sqlx.DB {
	return meta.MerchantDB
}

func GetSlaveDBInstance() *sqlx.DB {
	return meta.SlaveDB
}

func GetRedisInstance() *redis.Client {
	return meta.MerchantRedis
}

func Constructor(mt *MetaTable, uri string) {

	meta = mt
	meta.Rand = frand.New()
	session.New(mt.MerchantRedis, "lh8")
	loc, _ = time.LoadLocation("America/Sao_Paulo")

	ryrpc.Constructor(uri)
}

func pushLog(err error, code string) error {
	helper.InfoLog("%s---%s", err.Error(), code)
	return fmt.Errorf("系统错误 %s 错误代码:%s", err.Error(), code)
}

func Close() {
	//meta.MerchantBean.Conn.Release()
	meta.MerchantDB.Close()
	meta.MerchantRedis.Close()
	meta.SlaveDB.Close()
}

func MurmurHash(str string, seed uint32) uint64 {

	s := fmt.Sprintf("%s%d", str, seed)

	v := xxhash3.HashString(s)
	return v
}

func Lock(id string) error {

	val := fmt.Sprintf("%s:%s", defaultRedisKeyPrefix, id)
	ok, err := meta.MerchantRedis.SetNX(ctx, val, "1", LockTimeout).Result()
	if err != nil {
		return pushLog(err, helper.RedisErr)
	}
	if !ok {
		return errors.New(helper.RequestBusy)
	}

	return nil
}

func Unlock(id string) {
	val := fmt.Sprintf("%s:%s", defaultRedisKeyPrefix, id)
	meta.MerchantRedis.Unlink(ctx, val).Result()
}

func IpLocation(ipStr string) (string, string, string, error) {

	results, err := meta.IpDB.Get_all(ipStr)
	if err != nil {
		return "", "", "", err
	}

	return results.Country_long, results.Region, results.City, nil
}
func GetRedis() *redis.Client {
	return meta.MerchantRedis
}
